﻿using CNFM_CROCODILE_LOGO.Core.DBContext;
using CNFM_CROCODILE_LOGO.Core.Domain.Models;
using CNFM_CROCODILE_LOGO.Data.Mappings;
using CNFM_CROCODILE_LOGO.Data.RestClient;
using EFCore.BulkExtensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace CNFM_CROCODILE_LOGO.Data.DBContext
{
    public class EntityFrameworkDbContext : DbContext, IDbContext
    {

        public EntityFrameworkDbContext()
        {   //如果没有数据库，自动创建，有了什么都不干
            _ = Database.EnsureCreated();
        }


        // public DbSet<NewsInfo> NewsInfo { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {    //对于这个上下文重写此方法以配置要使用的数据库（和其他选项）。对于上下文的每个实例调用此方法创建。

            //加载appsetting.json
            IConfiguration configuration = new ConfigurationBuilder()
                 .SetBasePath(Directory.GetCurrentDirectory())
              .AddJsonFile("appsettings.json").Build();

            string connectionString = configuration["DBSetting:DefaultConnection"];

            //optionsBuilder.UseLazyLoadingProxies().UseSqlServer(connectionString);
            optionsBuilder.UseSqlServer(connectionString, p => p.UseRowNumberForPaging());

            base.OnConfiguring(optionsBuilder);

        }

        private void RegisterMaps(ModelBuilder builder)
        {
            // Full .NET Framework
            var maps = Assembly.GetExecutingAssembly().GetTypes()
                .Where(type => !string.IsNullOrWhiteSpace(type.Namespace)
                    && typeof(IBaseEntityTypeConfiguration).IsAssignableFrom(type) && type.IsClass).ToList();

            // .NET Core
            //var maps = typeof(a type in that assembly).GetTypeInfo().Assembly.GetTypes()
            //    .Where(type => !string.IsNullOrWhiteSpace(type.Namespace)
            //        && typeof(IBaseEntityTypeConfiguration).IsAssignableFrom(type) && type.IsClass).ToList();

            foreach (var item in maps)
                Activator.CreateInstance(item, BindingFlags.Public |
                BindingFlags.Instance, null, new object[] { builder }, null);
        }

        /// <summary>
        /// 动态添加Entity
        /// </summary> 
        /// <param name="modelBuilder"></param>
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //取基类=EntityBase 
            //var item = Assembly.GetEntryAssembly().GetTypes().Where(p => p.FullName.Contains("CNFM_CROCODILE_LOGO.Core")).FirstOrDefault();
            //var items = Assembly.GetEntryAssembly().GetTypes().Where(p => p.FullName.Contains("CNFM_CROCODILE_LOGO.Core"));

            var itemss = Assembly.Load("CNFM_CROCODILE_LOGO.Core");
            //  var item1 = items.GetEnumerator().GetType();

            var entityTypes = itemss.GetTypes()
                            .Where(type => !String.IsNullOrEmpty(type.Namespace))
                            .Where(type => type.GetTypeInfo().BaseType != null && type.GetTypeInfo().BaseType == typeof(BaseEntity));

            foreach (var type in entityTypes)
            {
                if (type.FullName.Contains("Entity"))
                    modelBuilder.Model.GetOrAddEntityType(type);
            }

            RegisterMaps(modelBuilder);
            base.OnModelCreating(modelBuilder);

        }

        /// <summary>
        /// Get DbSet
        /// </summary>
        /// <typeparam name="TEntity">Entity type</typeparam>
        /// <returns>DbSet</returns>
        public new DbSet<TEntity> Set<TEntity>() where TEntity : class, new()
        {
            return base.Set<TEntity>();
        }

        public IEnumerable<T> SqlQuery<T>(string sql, params object[] parameters) where T : class, new()
        {
            return this.Database.SqlQuery<T>(sql, parameters);
        }
        public void BulkInsert<T>(IList<T> entities, BulkConfig bulkConfig = null, Action<decimal> progress = null) where T : class
        {
            this.BulkInsertOrUpdate(entities, bulkConfig, progress);
        }
    }
}
